package com.hwapitest.utils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;



public class HttpRequestUtil {
    private static final Logger logger = Logger.getLogger(HttpRequestUtil.class);

    // 连接池管理器（全局共享）
    private static final PoolingHttpClientConnectionManager connManager;

    // 共享的HTTP客户端（支持连接池）
    private static final CloseableHttpClient httpClient;

    // 重试处理器
    private static final HttpRequestRetryHandler retryHandler;

    // 超时配置
    private static final RequestConfig requestConfig;

    static {
        // 初始化连接池
        connManager = new PoolingHttpClientConnectionManager();
        connManager.setMaxTotal(200);          // 最大连接数
        connManager.setDefaultMaxPerRoute(50); // 每个路由最大连接数

        // 配置重试策略
        retryHandler = new HttpRequestRetryHandler() {
            @Override
            public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
                if (executionCount >= 2) { // 最多重试2次
                    return false;
                }
                if (exception instanceof InterruptedIOException) {
                    // 超时不重试
                    return false;
                }
                if (exception instanceof ConnectTimeoutException) {
                    // 连接超时重试
                    return true;
                }
                // 其他情况重试
                return true;
            }
        };

        // 配置超时参数
        requestConfig = RequestConfig.custom()
                .setConnectTimeout(5000)    // 连接超时 5秒
                .setSocketTimeout(15000)    // 读取超时 15秒
                .setConnectionRequestTimeout(3000) // 请求超时 3秒
                .build();

        // 创建带连接池的HttpClient
        httpClient = HttpClients.custom()
                .setConnectionManager(connManager)
                .setRetryHandler(retryHandler)
                .setDefaultRequestConfig(requestConfig)
                .evictIdleConnections(30, TimeUnit.SECONDS) // 空闲连接超时
                .build();

        // 添加JVM关闭钩子
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                httpClient.close();
                connManager.close();
            } catch (IOException e) {
                logger.error("关闭HTTP客户端失败", e);
            }
        }));
    }

    /**
     * GET请求
     * @param url 请求URL
     * @param params 请求参数
     * @return 响应内容
     */
    public static String getRequest(String url, Map<String, String> params) {
        String res = "";
        StringBuilder urlBuilder = new StringBuilder(url);

        try {
            // 添加URL参数
            if (params != null && !params.isEmpty()) {
                boolean firstParam = true;
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    String encodedKey = URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8.name());
                    String encodedValue = URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name());

                    if (firstParam) {
                        urlBuilder.append("?").append(encodedKey).append("=").append(encodedValue);
                        firstParam = false;
                    } else {
                        urlBuilder.append("&").append(encodedKey).append("=").append(encodedValue);
                    }
                }
            }

            String finalUrl = urlBuilder.toString();
            logger.debug("Sending GET request to: " + finalUrl);

            HttpGet httpGet = new HttpGet(finalUrl);

            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                int statusCode = response.getStatusLine().getStatusCode();
                HttpEntity entity = response.getEntity();

                if (entity != null) {
                    res = EntityUtils.toString(entity, StandardCharsets.UTF_8);

                    if (logger.isDebugEnabled()) {
                        logger.debug("GET response [" + statusCode + "]: " +
                                shortenLongString(res, 300));
                    }
                } else {
                    logger.warn("GET request returned empty response body [" + statusCode + "]");
                }

                // 检查状态码
                if (statusCode >= HttpStatus.SC_BAD_REQUEST) {
                    String errorMsg = "GET request failed with status: " + statusCode;
                    logger.error(errorMsg);
                    throw new HttpException(errorMsg, statusCode, res);
                }
            }
        } catch (Exception e) {
            String errorMsg = "GET request execution failed: " + e.getMessage();
            logger.error(errorMsg, e);
            throw new RuntimeException(errorMsg, e);
        }

        return res;
    }

    /**
     * POST请求
     * @param url 请求URL
     * @param params 请求参数
     * @return 响应内容
     */
    public static String postRequest(String url, Map<String, String> params) {
        String res = "";
        HttpPost httpPost = new HttpPost(url);

        try {
            // 准备表单参数
            if (params != null && !params.isEmpty()) {
                List<NameValuePair> formParams = new ArrayList<>();
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }

                logger.debug("POST request parameters: " + formParams);
                httpPost.setEntity(new UrlEncodedFormEntity(formParams, StandardCharsets.UTF_8));
            }

            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                int statusCode = response.getStatusLine().getStatusCode();
                HttpEntity entity = response.getEntity();

                if (entity != null) {
                    res = EntityUtils.toString(entity, StandardCharsets.UTF_8);

                    if (logger.isDebugEnabled()) {
                        logger.debug("POST response [" + statusCode + "]: " +
                                shortenLongString(res, 300));
                    }
                } else {
                    logger.warn("POST request returned empty response body [" + statusCode + "]");
                }

                // 检查状态码
                if (statusCode >= HttpStatus.SC_BAD_REQUEST) {
                    String errorMsg = "POST request failed with status: " + statusCode;
                    logger.error(errorMsg);
                    throw new HttpException(errorMsg, statusCode, res);
                }
            }
        } catch (Exception e) {
            String errorMsg = "POST request execution failed: " + e.getMessage();
            logger.error(errorMsg, e);
            throw new RuntimeException(errorMsg, e);
        }

        return res;
    }


    /**
     * 发送HTTP请求
     * @param url 请求URL
     * @param requestType 请求类型 (GET/POST)
     * @param parameters 请求参数
     * @return 响应内容
     */
    public static String sendRequest(String url, String requestType, Map<String, String> parameters) {
        if (parameters == null) {
            parameters = new java.util.HashMap<>();
        }

        logger.info("Sending " + requestType.toUpperCase() + " request to: " + url);

        try {
            if ("get".equalsIgnoreCase(requestType)) {
                return getRequest(url, parameters);
            } else if ("post".equalsIgnoreCase(requestType)) {
                return postRequest(url, parameters);
            } else {
                String errorMsg = "Unsupported request type: " + requestType;
                logger.error(errorMsg);
                return errorMsg;
            }
        } catch (Exception e) {
            logger.error("Request execution failed! URL: " + url, e);
            throw e;
        }
    }

    // ==================== 辅助方法 ====================

    /**
     * 缩短长字符串（日志优化）
     * @param str 原始字符串
     * @param maxLength 最大显示长度
     * @return 缩短后的字符串
     */
    private static String shortenLongString(String str, int maxLength) {
        if (str == null) return "null";
        if (str.length() <= maxLength) return str;

        int partLength = maxLength / 2;
        return str.substring(0, partLength) +
                "\n... [truncated " + (str.length() - maxLength) + " chars] ...\n" +
                str.substring(str.length() - partLength);
    }

    /**
     * 自定义HTTP异常
     */
    public static class HttpException extends RuntimeException {
        private final int statusCode;
        private final String responseBody;

        public HttpException(String message, int statusCode, String responseBody) {
            super(message);
            this.statusCode = statusCode;
            this.responseBody = responseBody;
        }

        public int getStatusCode() {
            return statusCode;
        }

        public String getResponseBody() {
            return responseBody;
        }

        @Override
        public String toString() {
            return "HttpException{" +
                    "statusCode=" + statusCode +
                    ", message='" + getMessage() + '\'' +
                    ", responseBody='" + responseBody + '\'' +
                    '}';
        }
    }

    // ==================== 连接池监控方法 ====================

    /**
     * 获取连接池状态信息
     * @return 连接池状态字符串
     */
    public static String getConnectionPoolStats() {
        return "Connection pool stats: " +
                "Total=" + connManager.getTotalStats().getAvailable() + "/" + connManager.getTotalStats().getLeased() +
                ", MaxTotal=" + connManager.getMaxTotal();
    }

    /**
     * 关闭连接池资源
     */
    public static void shutdown() {
        try {
            httpClient.close();
            connManager.close();
            logger.info("HTTP connection pool shutdown successfully");
        } catch (IOException e) {
            logger.error("Failed to shutdown HTTP connection pool", e);
        }
    }
}
